We want a surface so we can properly represent the scale factor for it.
All backends are converted to use surfaces and we reimplement the
backwards compat code in the generic code.
G_DEFINE_TYPE (GdkBroadwayCursor, gdk_broadway_cursor, GDK_TYPE_CURSOR)
-static GdkPixbuf* gdk_broadway_cursor_get_image (GdkCursor *cursor);
+static cairo_surface_t * gdk_broadway_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
static void
gdk_broadway_cursor_finalize (GObject *object)
object_class->finalize = gdk_broadway_cursor_finalize;
- cursor_class->get_image = gdk_broadway_cursor_get_image;
+ cursor_class->get_surface = gdk_broadway_cursor_get_surface;
}
static void
return GDK_CURSOR (private);
}
-static GdkPixbuf*
-gdk_broadway_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_broadway_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
g_return_val_if_fail (cursor != NULL, NULL);
#include "config.h"
+#define GDK_PIXBUF_ENABLE_BACKEND
+#include <gdk-pixbuf/gdk-pixbuf.h>
+
#include "gdkcursor.h"
#include "gdkcursorprivate.h"
#include "gdkdisplayprivate.h"
#include "gdkintl.h"
#include "gdkinternals.h"
+#include <math.h>
/**
* SECTION:cursors
*/
GdkPixbuf*
gdk_cursor_get_image (GdkCursor *cursor)
+{
+ int w, h;
+ cairo_surface_t *surface;
+ GdkPixbuf *pixbuf;
+ gchar buf[32];
+ double x_hot, y_hot;
+ double x_scale, y_scale;
+
+ g_return_val_if_fail (GDK_IS_CURSOR (cursor), NULL);
+
+ surface = gdk_cursor_get_surface (cursor, &x_hot, &y_hot);
+ if (surface == NULL)
+ return NULL;
+
+ w = cairo_image_surface_get_width (surface);
+ h = cairo_image_surface_get_height (surface);
+
+ x_scale = y_scale = 1;
+#ifdef HAVE_CAIRO_SURFACE_SET_DEVICE_SCALE
+ cairo_surface_get_device_scale (surface, &x_scale, &y_scale);
+#endif
+
+ pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, w, h);
+ cairo_surface_destroy (surface);
+
+ if (x_scale != 1)
+ {
+ GdkPixbuf *old;
+
+ old = pixbuf;
+ pixbuf = gdk_pixbuf_scale_simple (old,
+ w / x_scale, h / y_scale,
+ GDK_INTERP_HYPER);
+ g_object_unref (old);
+ }
+
+
+ g_snprintf (buf, 32, "%d", (int)x_hot);
+ gdk_pixbuf_set_option (pixbuf, "x_hot", buf);
+
+ g_snprintf (buf, 32, "%d", (int)y_hot);
+ gdk_pixbuf_set_option (pixbuf, "y_hot", buf);
+
+ return pixbuf;
+}
+
+/**
+ * gdk_cursor_get_surface:
+ * @cursor: a #GdkCursor
+ * @x_hot: Location to store the hotspot x position, or %NULL
+ * @y_hot: Location to store the hotspot y position, or %NULL
+ *
+ * Returns a #cairo_surface_t (image surface) with the image used to display the cursor.
+ *
+ * Note that depending on the capabilities of the windowing system and
+ * on the cursor, GDK may not be able to obtain the image data. In this
+ * case, %NULL is returned.
+ *
+ * Returns: (transfer full): a #cairo_surface_t representing @cursor, or %NULL
+ *
+ * Since: 3.10
+ */
+cairo_surface_t *
+gdk_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
g_return_val_if_fail (GDK_IS_CURSOR (cursor), NULL);
- return GDK_CURSOR_GET_CLASS (cursor)->get_image (cursor);
+ return GDK_CURSOR_GET_CLASS (cursor)->get_surface (cursor,
+ x_hot, y_hot);
}
void gdk_cursor_unref (GdkCursor *cursor);
GDK_AVAILABLE_IN_ALL
GdkPixbuf* gdk_cursor_get_image (GdkCursor *cursor);
+GDK_AVAILABLE_IN_3_10
+cairo_surface_t *gdk_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
GDK_AVAILABLE_IN_ALL
GdkCursorType gdk_cursor_get_cursor_type (GdkCursor *cursor);
{
GObjectClass parent_class;
- GdkPixbuf * (* get_image) (GdkCursor * cursor);
+ cairo_surface_t * (* get_surface) (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
};
G_END_DECLS
G_DEFINE_TYPE (GdkQuartzCursor, gdk_quartz_cursor, GDK_TYPE_CURSOR)
-static GdkPixbuf *gdk_quartz_cursor_get_image (GdkCursor *cursor);
+static cairo_surface_t *gdk_quartz_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
static void
gdk_quartz_cursor_finalize (GObject *object)
object_class->finalize = gdk_quartz_cursor_finalize;
- cursor_class->get_image = gdk_quartz_cursor_get_image;
+ cursor_class->get_surface = gdk_quartz_cursor_get_surface;
}
static void
return cursor_private->nscursor;
}
-static GdkPixbuf *
-gdk_quartz_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_quartz_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
/* FIXME: Implement */
return NULL;
G_OBJECT_CLASS (_gdk_wayland_cursor_parent_class)->finalize (object);
}
-static GdkPixbuf*
-gdk_wayland_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_wayland_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
return NULL;
}
object_class->finalize = gdk_wayland_cursor_finalize;
- cursor_class->get_image = gdk_wayland_cursor_get_image;
+ cursor_class->get_surface = gdk_wayland_cursor_get_surface;
}
static void
}
GdkPixbuf *
-gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon)
+gdk_win32_icon_to_pixbuf_libgtk_only (HICON hicon, gint *x_hot, gint *y_hot)
{
GdkPixbuf *pixbuf = NULL;
ICONINFO ii;
}
}
- g_snprintf (buf, sizeof (buf), "%ld", ii.xHotspot);
- gdk_pixbuf_set_option (pixbuf, "x_hot", buf);
-
- g_snprintf (buf, sizeof (buf), "%ld", ii.yHotspot);
- gdk_pixbuf_set_option (pixbuf, "y_hot", buf);
+ if (x_hot)
+ *x_hot = ii.xHotspot;
+ if (y_hot)
+ *y_hot = ii.yHotspot;
/* release temporary resources */
out2:
return pixbuf;
}
-static GdkPixbuf *
-_gdk_win32_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+_gdk_win32_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
+ GdkPixbuf *pixbuf;
+ cairo_surface_t *surface
+
g_return_val_if_fail (cursor != NULL, NULL);
- return gdk_win32_icon_to_pixbuf_libgtk_only (((GdkWin32Cursor *) cursor)->hcursor);
+ pixbuf = gdk_win32_icon_to_pixbuf_libgtk_only (((GdkWin32Cursor *) cursor)->hcursor, x_hot, y_hot);
+
+ if (pixbuf == NULL)
+ return NULL;
+
+ surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, NULL);
+ g_object_unref (pixbuf);
+
+ return surface;
}
GdkCursor *
object_class->finalize = _gdk_win32_cursor_finalize;
- cursor_class->get_image = _gdk_win32_cursor_get_image;
+ cursor_class->get_surface = _gdk_win32_cursor_get_surface;
}
G_DEFINE_TYPE (GdkX11Cursor, gdk_x11_cursor, GDK_TYPE_CURSOR)
-static GdkPixbuf* gdk_x11_cursor_get_image (GdkCursor *cursor);
+static cairo_surface_t *gdk_x11_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot);
static void
gdk_x11_cursor_finalize (GObject *object)
object_class->finalize = gdk_x11_cursor_finalize;
- cursor_class->get_image = gdk_x11_cursor_get_image;
+ cursor_class->get_surface = gdk_x11_cursor_get_surface;
}
static void
#if defined(HAVE_XCURSOR) && defined(HAVE_XFIXES) && XFIXES_MAJOR >= 2
-static GdkPixbuf*
-gdk_x11_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_x11_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
+ GdkDisplay *display;
Display *xdisplay;
GdkX11Cursor *private;
XcursorImages *images = NULL;
XcursorImage *image;
gint size;
- gchar buf[32];
- guchar *data, *p, tmp;
- GdkPixbuf *pixbuf;
+ cairo_surface_t *surface;
+ gint scale;
gchar *theme;
private = GDK_X11_CURSOR (cursor);
-
- xdisplay = GDK_DISPLAY_XDISPLAY (gdk_cursor_get_display (cursor));
+
+ display = gdk_cursor_get_display (cursor);
+ xdisplay = GDK_DISPLAY_XDISPLAY (display);
size = XcursorGetDefaultSize (xdisplay);
theme = XcursorGetTheme (xdisplay);
image = images->images[0];
- data = g_malloc (4 * image->width * image->height);
- memcpy (data, image->pixels, 4 * image->width * image->height);
+ /* Assume the currently set cursor was defined for the screen
+ scale */
+ scale =
+ gdk_screen_get_monitor_scale_factor (gdk_display_get_default_screen (display), 0);
- for (p = data; p < data + (4 * image->width * image->height); p += 4)
- {
- tmp = p[0];
- p[0] = p[2];
- p[2] = tmp;
- }
+ surface = gdk_window_create_similar_image_surface (NULL,
+ CAIRO_FORMAT_ARGB32,
+ image->width,
+ image->height,
+ scale);
+
+ memcpy (cairo_image_surface_get_data (surface),
+ image->pixels, 4 * image->width * image->height);
- pixbuf = gdk_pixbuf_new_from_data (data, GDK_COLORSPACE_RGB, TRUE,
- 8, image->width, image->height,
- 4 * image->width,
- (GdkPixbufDestroyNotify)g_free, NULL);
+ cairo_surface_mark_dirty (surface);
- if (private->name)
- gdk_pixbuf_set_option (pixbuf, "name", private->name);
- g_snprintf (buf, 32, "%d", image->xhot);
- gdk_pixbuf_set_option (pixbuf, "x_hot", buf);
- g_snprintf (buf, 32, "%d", image->yhot);
- gdk_pixbuf_set_option (pixbuf, "y_hot", buf);
+ if (x_hot)
+ *x_hot = (double)image->xhot / scale;
+ if (y_hot)
+ *y_hot = (double)image->yhot / scale;
XcursorImagesDestroy (images);
- return pixbuf;
+ return surface;
}
void
#else
-static GdkPixbuf*
-gdk_x11_cursor_get_image (GdkCursor *cursor)
+static cairo_surface_t *
+gdk_x11_cursor_get_surface (GdkCursor *cursor,
+ gdouble *x_hot,
+ gdouble *y_hot)
{
return NULL;
}